/**
 * 版权所有(C)，上海海鼎信息工程股份有限公司，2007，所有权利保留。
 * 
 * 项目名：	rumba
 * 文件名：	HRecord.java
 * 模块说明：	
 * 修改历史：
 * Aug 24, 2007 - lxm - 创建。
 */
package com.hd123.rumba.jsp.table;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import com.hd123.rumba.exception.BusinessException;
import com.hd123.rumba.util.AccessMode;
import com.hd123.rumba.util.XMLUtil;

/**
 * 数据记录。
 * 
 * @author lxm
 * 
 */
public class HRecord {

  private HashMap<String, Object> valueMap = new HashMap<String, Object>();
  private HDataset dataset;

  /** 所属数据集 */
  public HDataset getDataset() {
    return this.dataset;
  }

  void setDataset(HDataset dataset) {
    this.dataset = dataset;
  }

  /**
   * 取得指定字段值。
   * 
   * @param fieldName
   *          指定字段名。
   * @return 返回字段取值。
   * @throws BusinessException
   */
  public Object getValue(String fieldName) throws BusinessException {
    assert this.dataset != null;
    if (this.dataset.getFieldDefByName(fieldName) != null)
      throw new BusinessException("指定的字段(字段名=" + fieldName + ")尚未被在数据集中被定义。");
    return this.valueMap.get(fieldName);
  }

  /**
   * 设置字段值。
   * 
   * @param fieldName
   *          指定字段名。
   * @param value
   *          指定字段取值。
   * @throws BusinessException
   */
  public void setValue(String fieldName, Object value) throws BusinessException {
    assert this.dataset != null;
    if (this.dataset.getFieldDefByName(fieldName) == null)
      throw new BusinessException("指定的字段(字段名=" + fieldName + ")尚未被在数据集中被定义。");
    this.valueMap.put(fieldName, value);
  }

  /**
   * 取得当前记录在所属数据集{@link #dataset}中的索引。
   * 
   * @return 当出现异常时将返回-1。
   */
  public int getIndex() {
    try {
      return this.dataset.getFieldDefs().indexOf(this);
    } catch (Throwable t) {
      return -1;
    }
  }

  void writeToXml(Document doc, Element root, AccessMode am) {
    assert this.dataset != null;

    Element e = doc.createElement("record");

    for (HFieldDef fieldDef : this.dataset.getFieldDefs()) {
      String fieldName = fieldDef.getName();
      String dataType = fieldDef.getDataType();

      String permId = fieldDef.getPermissionId();
      if (permId != null) {
        int mode = am.getAccessMode(fieldDef.getPermissionId());
        if (mode == -1)
          continue;
      }

      Object value = this.valueMap.get(fieldName);
      if (HFieldDef.VALUE_DATATYPE_INTEGER.equals(dataType))
        XMLUtil.writeInteger(e, fieldName, (Integer) value);
      else if (HFieldDef.VALUE_DATATYPE_PRICE.equals(dataType)
          || HFieldDef.VALUE_DATATYPE_MONEY.equals(dataType)
          || HFieldDef.VALUE_DATATYPE_RATE.equals(dataType)
          || HFieldDef.VALUE_DATATYPE_QUANTITY.equals(dataType))
        XMLUtil.writeBigDecimal(e, fieldName, (BigDecimal) value);
      else if (HFieldDef.VALUE_DATATYPE_DATE.equals(dataType)
          || HFieldDef.VALUE_DATATYPE_TIME.equals(dataType)
          || HFieldDef.VALUE_DATATYPE_DATETIME.equals(dataType))
        XMLUtil.writeDate(e, fieldName, (Date) value);
      else if (HFieldDef.VALUE_DATATYPE_TEXT.equals(dataType))
        XMLUtil.writeString(e, fieldName, (String) value);
      else if (HFieldDef.VALUE_DATATYPE_BOOLEAN.equals(dataType))
        XMLUtil.writeBoolean(e, fieldName, (Boolean) value);
    }

    root.appendChild(e);
  }

  void readFromXml(Element e) throws BusinessException {
    assert this.dataset != null;

    try {

      for (HFieldDef fieldDef : this.dataset.getFieldDefs()) {
        String fieldName = fieldDef.getName();
        String dataType = fieldDef.getDataType();

        Object value = null;
        if (HFieldDef.VALUE_DATATYPE_INTEGER.equals(dataType))
          value = XMLUtil.readInteger(e, fieldName);
        else if (HFieldDef.VALUE_DATATYPE_PRICE.equals(dataType)
            || HFieldDef.VALUE_DATATYPE_MONEY.equals(dataType)
            || HFieldDef.VALUE_DATATYPE_RATE.equals(dataType)
            || HFieldDef.VALUE_DATATYPE_QUANTITY.equals(dataType))
          value = XMLUtil.readBigDecimal(e, fieldName);
        else if (HFieldDef.VALUE_DATATYPE_DATE.equals(dataType)
            || HFieldDef.VALUE_DATATYPE_TIME.equals(dataType)
            || HFieldDef.VALUE_DATATYPE_DATETIME.equals(dataType))
          value = XMLUtil.readDate(e, fieldName);
        else if (HFieldDef.VALUE_DATATYPE_TEXT.equals(dataType))
          value = XMLUtil.readString(e, fieldName);
        else if (HFieldDef.VALUE_DATATYPE_BOOLEAN.equals(dataType))
          value = XMLUtil.readBoolean(e, fieldName);
        
        this.valueMap.put(fieldName, value);
      }
    } catch (Exception ex) {
      throw new BusinessException(ex);
    }
  }

}
